package com.futao.file;

import com.futao.entity.User;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import sun.nio.ch.FileKey;

import java.io.*;
import java.util.Arrays;

/**
 * @author futao
 * Created on 18-6-12-上午9:52.
 * <p>
 * (1)java文件模型
 * 在硬盘上的文件是byte byte byte存储的，是数据的集合
 * (2)打开文件
 * 有两种模式(rw)和(r)
 * RandomAccessFile raf= new RandomAccessFile(file,"rw");
 * 文件指针，打开时在问开头pointer=0;
 * (3)写
 * raf.write()  只写一个字节(后8位
 * (4)读
 * int b =raf.read() 读取一个字节
 * (5) 文件读写完毕之后要关闭
 */
@Slf4j
public class FileUtilsByteStream {

    /**
     * 文件和目录操作--访问与创建
     *
     * @param path
     * @throws IOException
     */
    public void fileUtils(String path) throws IOException {
        /*根据地址得到一个文件或者目录*/
        File file = new File(path);
        /*判断文件（目录）是否存在*/
        if (!file.exists() && file.isDirectory()) {
            log.info("目录不存在，正在创建目录...");
            /*创建目录*/
            boolean mkdir = file.mkdir();
        }
        if (!file.exists() && file.isFile()) {
            log.info("文件不存在，正在创建文件...");
            /*创建文件*/
            boolean newFile = file.createNewFile();
        }
        /*遍历目录下的直接子文件（目录）*/
//        String[] nameList = file.list();
//        for (String name : nameList) {
//            log.info("name:" + name);
//        }
        /*递归遍历所有文件和目录*/
        File[] listFiles = file.listFiles();
        if (listFiles != null && listFiles.length > 0) {
            for (File file1 : listFiles) {
                if (file1.isDirectory()) {
                    log.info(file1.getName() + "目录,继续遍历");
                    fileUtils(file1.getAbsolutePath());
                } else {
                    log.info("文件：" + file1.getName());
                }
            }
        }
    }

    @Test
    public void fun1() throws IOException {
        long start = System.currentTimeMillis();
//        fileUtils("/home/futao/Desktop/template/service/src/main/java/com/futao");
//        readAndWrite("/home/futao/Desktop/template/uploadFiles");
//        copyFile(new File("/home/futao/Desktop/data.sql"), new File("/home/futao/Desktop/data1.sql"));
        copyFileByBuffer(new File("/home/futao/Desktop/data.sql"), new File("/home/futao/Desktop/data2.sql"));
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    /**
     * 读写文件
     *
     * @param dirPath
     * @throws IOException
     */
    public void readAndWrite(String dirPath) throws IOException {
        File file = new File(dirPath, "testFile.txt");
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        /*指针的位置*/
        System.out.println(randomAccessFile.getFilePointer());
        randomAccessFile.write('A');

        randomAccessFile.write('B');
        randomAccessFile.writeInt(0x7ffffff);

        System.out.println(randomAccessFile.getFilePointer());

        //读取文件,指针放在文件开始位置
        randomAccessFile.seek(0);
        byte[] bytes = new byte[(int) randomAccessFile.length()];
        randomAccessFile.read(bytes);

        String s = new String(bytes);
        System.out.println(s);

        System.out.println(Arrays.toString(bytes));

        randomAccessFile.close();
    }

    /**
     * IO流
     * 字节流,字符流
     * 1.字节流
     * （1）InputStream，OutputStream
     * InputStream抽象了应用程序读取数据的方式
     * OutputStream抽象了应用程序写出数据的方式
     * （2）EOF=End或者读到-1表示结尾
     * <p>
     * 读取大文件：创建byte数组，每次读取byte大小的文件，并且记录读取的起点和终点，如果文件没有读取完，则下一次从上一次的重点开始读取
     */
    public void ioUtils(String fileName) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(fileName);
        byte[] bytes = new byte[20 * 1024];
        fileInputStream.read(bytes, 0, bytes.length);
        //...
    }

    /**
     * 复制文件
     *
     * @param fromFile
     * @param toFile
     * @throws IOException
     */
    public void copyFile(File fromFile, File toFile) throws IOException {
        if (!fromFile.exists()) {
            throw new IllegalArgumentException(fromFile + "不存在");
        }
        if (!fromFile.isFile()) {
            throw new IllegalArgumentException(fromFile + "不是一个文件");
        }
        @Cleanup
        FileInputStream fileInputStream = new FileInputStream(fromFile);
        @Cleanup
        FileOutputStream fileOutputStream = new FileOutputStream(toFile);
        byte[] bytes = new byte[8 * 1024];
        int totalBytes;
        while ((totalBytes = fileInputStream.read(bytes, 0, bytes.length)) != -1) {
            fileOutputStream.write(bytes, 0, totalBytes);
            fileOutputStream.flush();
        }
    }

    /**
     * DataOutputStream
     * 对FileOutputStream进行了封装
     *
     * @throws IOException
     */
    @Test
    public void test2() throws IOException {
        @Cleanup
        DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(new File("/home/futao/Desktop/template/uploadFiles/testFile.txt")));
        dataOutputStream.writeUTF("中国");
    }

    /**
     * 通过缓冲区拷贝文件
     *
     * @throws IOException
     */
    @Test
    public void copyFileByBuffer(File fromFile, File toFile) throws IOException {
//        File fromFile = new File("/home/futao/Desktop/Spring Boot Reference1.5.4.pdf");
//        File toFile = new File("/home/futao/Desktop/Spring Boot Reference1.5.pdf");
        if (!fromFile.exists()) {
            throw new IllegalArgumentException(fromFile + "不存在");
        }
        if (!fromFile.isFile()) {
            throw new IllegalArgumentException(fromFile + "不是一个文件");
        }
        @Cleanup
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(fromFile));
        @Cleanup
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(toFile));
        int totalBytes;
        while ((totalBytes = bufferedInputStream.read()) != -1) {
            bufferedOutputStream.write(totalBytes);
            bufferedOutputStream.flush();//刷新缓冲区
        }
    }

    /**
     * 序列化与反序列化
     *
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Test
    public void obj() throws IOException, ClassNotFoundException {
        @Cleanup
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("/home/futao/Desktop/template/uploadFiles/testFile.txt")));
        objectOutputStream.writeObject(new User("付韬", 18, "pwd"));
        objectOutputStream.flush();
        objectOutputStream.close();

        @Cleanup
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("/home/futao/Desktop/template/uploadFiles/testFile.txt")));
        User user = (User) objectInputStream.readObject();
        System.out.println(user);
    }
}
